/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MainClasses;
import java.util.*;
import MainClasses.FromAPCompSci.*;

/**
 *
 * @author andrewcutler
 */
public class MyDate {
    
    
    
    public static String FORMAT_1 = "mm/dd/yyyy";
    public static String FORMAT_2 = "dd/mm/yyyy";
    public static String FORMAT_3 = "yyyy/mm/dd";
    
    
    private int month;
    private int year;
    private int dayofmonth;
    private int day;
    
    
    
    public MyDate(int dayofmonth, int month, int year)
    {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.DAY_OF_MONTH, dayofmonth);
        cal.set(Calendar.MONTH, month);
        cal.set(Calendar.YEAR, year);
        
        init(dayofmonth, month, year, cal.get(Calendar.DAY_OF_WEEK));
    }
    
    private void init(int dom, int m, int y, int d)
    {
        dayofmonth = dom;
        month = m;
        year = y;
        day = d;
        if(day > 7)
            System.out.println("Error: " + day + " > 7");
    }
    
    
    public int getMonth()
    {
        return month;
        
    }
    
    public int getYear()
    {
        return year;
    }
    
    public int getDayOfMonth()
    {
        return dayofmonth;
    }
    
    public String toString(String format, String divider)
    {
        String d = "" + dayofmonth;
        String m = "" + month;
        String y = "" + year;
        if(dayofmonth < 10)
        {
            d = "0"+d;
        }
        if(month < 10)
        {
            m = "0"+m;
        }
        
        if(format.equals(MyDate.FORMAT_1))
        {
            return m+divider+d+divider+y;
        }
        if(format.equals(MyDate.FORMAT_2))
        {
            return d+divider+m+divider+y;
        }
        if(format.equals(MyDate.FORMAT_3))
        {
            return y+divider+m+divider+d;
        }
        return null;
    }
    
    @Override
    public boolean equals(Object o)
    {
        if(o instanceof MyDate && dayofmonth == ((MyDate)o).getDayOfMonth() && month == ((MyDate)o).getMonth() && year == ((MyDate)o).getYear())
            return true;
        return false;  
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 43 * hash + this.month;
        hash = 43 * hash + this.year;
        hash = 43 * hash + this.dayofmonth;
        return hash;
    }
    
    public String getDayOfWeek()
    {
        return days[day-1];
    }
    
    public String getStringedMonth()
    {
        return months[month - 1];
    }
    
    public int getDay()
    {
        return this.CalcFirstOfMonth(year, month-1);
    }
         
    public static MyDate getDate(int modifier)
    {
        try
        {
            GregorianCalendar greg = new GregorianCalendar();
            greg.add(Calendar.DAY_OF_MONTH, modifier);
            return new MyDate(greg.get(Calendar.DAY_OF_MONTH), greg.get(Calendar.MONTH)+1, greg.get(Calendar.YEAR));
        }
        catch(Exception e)
        {
            main.error(e);
            return null;
        }
    }
    
    public static MyDate getToday()
    {
        return MyDate.getDate(0);
    }
    
    public static MyDate getTomorrow()
    {
        return MyDate.getDate(1);
    }
    
    public boolean isLeapYear()
    {
        if(year % 4 == 0)
            return true;
        return false;
    }
   
    public int getDaysInMonth()
    {
        int[] daysInMonth = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if(isLeapYear())
        {
            daysInMonth[1] = 29;
        }
        else
        {
            daysInMonth[1] = 28;
        }
        
        return daysInMonth[month-1];
    }
    
    // Date must have divider "-"
    public static MyDate parseDate(String s, String format)
    {
        if(format.equals(MyDate.FORMAT_2))
        {
            int day = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int month = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int year = Integer.parseInt(s);
            return new MyDate(day, month, year);
        }
        else if(format.equals(MyDate.FORMAT_1))
        {
            int month = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int day = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int year = Integer.parseInt(s);
            return new MyDate(day, month, year);
        }
        else if(format.equals(MyDate.FORMAT_3))
        {
            int year = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int month = Integer.parseInt(s.substring(0, s.indexOf("-")));
            s = s.substring(s.indexOf("-")+1);
            int day = Integer.parseInt(s);
            return new MyDate(day, month, year);
        }
        return null;
        
    }
    
    
    
    public static int january = 1;
    public static int february = 2;
    public static int march = 3;
    public static int april = 4; 
    public static int may = 5;
    public static int june = 6;
    public static int july = 7;
    public static int august = 8;
    public static int september = 9;
    public static int october = 10;
    public static int november = 11;
    public static int december = 12;
    
    public static String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
                   "Thursday", "Friday", "Saturday"};

  public static String months[] = {"January", "February", "March", "April",
                     "May", "June", "July", "August", "September",
                     "October", "November", "December"};

  public static int DaysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    
    public int CalcFirstOfMonth(int year, int month)
  /*
     USE:  Calculates day of the week the first day of the month falls on.
     IN:   year = given year after 1582 (start of the Gregorian calendar).
           month = 0 for January, 1 for February, etc.
     OUT:  First day of month: 0 = Sunday, 1 = Monday, etc.
  */
    {
    int firstDay;       /* day of week for Jan 1, then first day of month */
    int i;              /* to traverse months before given month */
  
    /* Start at 1582, when modern calendar starts. */
    if (year < 1582) return (-1);
  
    /* Catch month out of range. */
    if ((month < 0) || (month > 11)) return (-1);
  
    /* Get day of week for Jan 1 of given year. */
    firstDay = CalcJanuaryFirst(year);
  
    /* Increase firstDay by days in year before given month to get first day
     * of month.
     */
    for (i = 0; i < month; i++)
      firstDay += DaysInMonth[i];
  
    /* Increase by one if month after February and leap year. */
    if ((month > 1) && IsLeapYear(year)) firstDay++;
  
    /* Convert to day of the week and return. */
    return (firstDay % 7);
    } // CalcFirstOfMonth
  
  public static boolean IsLeapYear(int year)
  /*
     USE:  Determines if given year is a leap year.
     IN:   year = given year after 1582 (start of the Gregorian calendar).
     OUT:  TRUE if given year is leap year, FALSE if not.
     NOTE: Formulas capture definition of leap years; cf CalcLeapYears().
  */
    {
  
    /* If multiple of 100, leap year iff multiple of 400. */
    if ((year % 100) == 0) return((year % 400) == 0);
  
    /* Otherwise leap year iff multiple of 4. */
    return ((year % 4) == 0);
    } // IsLeapYear
  
  int CalcJanuaryFirst(int year)
  /*
     USE:  Calculate day of the week on which January 1 falls for given year.
     IN:   year = given year after 1582 (start of the Gregorian calendar).
     OUT:  Day of week for January 1: 0 = Sunday, 1 = Monday, etc.
     NOTE: Formula starts with a 5, since January 1, 1582 was a Friday; then
           advances the day of the week by one for every year, adding the
           number of leap years intervening, because those years Jan 1
           advanced by two days. Calculate mod 7 to get the day of the week.
  */
    {
    /* Start at 1582, when modern calendar starts. */
    if (year < 1582) return (-1);
  
    /* Start Fri 01-01-1582; advance a day for each year, 2 for leap yrs. */
    return ((5 + (year - 1582) + CalcLeapYears(year)) % 7);
    } // CalcJanuaryFirst
  
  int CalcLeapYears(int year)
  /*
     USE:  Calculate number of leap years since 1582.
     IN:   year = given year after 1582 (start of the Gregorian calendar).
     OUT:  number of leap years since the given year, -1 if year < 1582
     NOTE: Count doesn't include the given year if it is a leap year.
           In the Gregorian calendar, used since 1582, every fourth year
           is a leap year, except for years that are a multiple of a
           hundred, but not a multiple of 400, which are no longer leap
           years. Years that are a multiple of 400 are still leap years:
           1700, 1800, 1990 were not leap years, but 2000 will be.
  */
    {
    int leapYears;      /* number of leap years to return */
    int hundreds;       /* number of years multiple of a hundred */
    int fourHundreds;   /* number of years multiple of four hundred */
  
    /* Start at 1582, when modern calendar starts. */
    if (year < 1582) return (-1);
  
    /* Calculate number of years in interval that are a multiple of 4. */
    leapYears = (year - 1581) / 4;
  
    /* Calculate number of years in interval that are a multiple of 100;
     * subtract, since they are not leap years.
     */
    hundreds = (year - 1501) / 100;
    leapYears -= hundreds;
  
    /* Calculate number of years in interval that are a multiple of 400;
     * add back in, since they are still leap years.
     */
    fourHundreds = (year - 1201) / 400;
    leapYears += fourHundreds;
  
    return (leapYears);
    } // CalcLeapYears

}
